# Author: Chris Moyer
# URL Mapper based on GAE

import logging
import re
import sys
import traceback

import marajo
import mimetypes
from marajo.utils import find_class
from marajo.appengine.ext import webapp
from marajo.appengine.handlers import Request, Response, RequestHandler
from marajo.appengine.handlers.static import StaticHandler

log = logging.getLogger("marajo.urlmapper")

class URLMapper(object):
    """
    Simple URL mapper
    """

    def __call__(self, environ, start_response):
        """
        This needs to be callable as a function
        """
        # This is a god aweful hack because HTTPlib is NOT threadsafe
        # we essentially have to re-connect to SDB for every thread we're in
        # which must be set up in each model object loaded
        from boto.sdb.db.model import Model
        from boto.sdb.db.manager import get_manager
        for cls in Model.__sub_classes__:
            cls._manager = get_manager(cls)

        request = Request(environ)
        log.info("%s: %s" % (request.method, request.path_info))

        hand = self.get_handler(request)
        if hand:
            response = hand.call()
        else:
            hand = RequestHandler(marajo.config, request, Response())
            hand.error(404)
            log.error("Not Found: %s" % request.path)
        return hand.response.wsgi_write(environ, start_response)

    def get_handler(self, request):
        """
        Get the handler for this request, or None if there's none found
        """
        # Initialize the variables
        # This is required because
        # we're about to screw with some things
        # in the request object
        # These next two lines tell webob to initialize
        # the GET and POST variables
        request.POST
        request.GET

        # Split out the content_type requested from the
        # rest of the handler
        path_groups = request.path.split(".")
        if len(path_groups) > 1:
            file_extension = path_groups[-1]
        else:
            file_extension = "html"
        content_type = mimetypes.guess_type(".%s" % file_extension)[0]
        if not content_type:
            content_type = mimetypes.guess_type(".html")[0]
            path_info = request.path
        else:
            path_info = path_groups[0]

        for handler_config in marajo.config['handlers']:
            if handler_config.has_key("static_dir"):
                pattern = "^%s"
            else:
                pattern = "^%s$"

            if handler_config.has_key("static_dir")  or handler_config.get("content_negotiation", True) == False:
                path = request.path
            else:
                path = path_info

            match = re.match(pattern % handler_config['url'], path)
            if match:
                if not handler_config.has_key("static_dir")  and handler_config.get("content_negotiation", True):
                    request.file_extension = file_extension
                else:
                    request.file_extension = "html"
                request.match_groups = match.groups()
                log.debug("URL Mapping: %s" % handler_config)
                if len(match.groups()) > 0:
                    request.script_name = match.group(0)[:match.start(1)]
                    request.path_info = match.group(0)[match.start(1):]
                    log.debug("script_name: %s " % request.script_name)
                else:
                    request.path_info = path
                if handler_config.has_key("handler"):
                    handler_class = find_class(handler_config['handler'])
                    conf = marajo.config.copy()
                    conf.update(handler_config)
                    return  handler_class(conf, request, Response())
                elif handler_config.has_key("static_dir") or handler_config.has_key("static_file"):
                    return StaticHandler(handler_config, request, Response())
        return None
